#include "../include/RtmpRecv.h"
#include "../include/SockInit.h"

RtmpRecv::RtmpRecv(const string& s_url, const string file_name, 
    int sockfd, uint16_t port, const string& destIP, uint16_t destPort,
    int fps) :
    url(s_url),
    fileName(file_name),
    destIP(destIP),
    destPort(destPort),
    FPS(fps)
{
    // RTMP 流相关变量初始化
    bufSize = RTP_MAX_PKT_SIZE;
    buf = (char *)malloc(bufSize);
    memset(buf, 0, bufSize);
    countBufSize = 0;
    bLiveStream = true;
    rtmp = RTMP_Alloc();    // 创建一个RTMP会话的句柄

    rtpPacket = new RtpPacket();
    rtpInstance = new RtpInstance(sockfd, port, destIP, destPort);
};


RtmpRecv::~RtmpRecv()
{
    // RTMP 相关变量: fp, buf and rtmp
    if (fp != nullptr) {
        fclose(fp);
        fp = nullptr;
    }
    if (buf != nullptr) {
        free(buf);
        buf = nullptr;
    }
    if (rtmp != nullptr) {
        RTMP_Close(rtmp);
        RTMP_Free(rtmp);
        rtmp = nullptr;
    }

    // rtp 相关变量
    delete rtpPacket;
    delete rtpInstance;

    CleanupSockets();
}

int RtmpRecv::init()
{
    fp = fopen(fileName.c_str(), "wb");
    if (!fp) {
        RTMP_LogPrintf("Open File Failed!\n");
        return 0;
    }

    /* set log level */
    // RTMP_LogLevel loglvl = RTMP_LOGDEBUG;
    // RTMP_LogSetLevel(loglvl);

    cout << "InitRTMPConn..." << endl;
    InitSockets();
    RTMP_Init(rtmp);

    // set connection timeout,default 30s
    rtmp->Link.timeout = 10;	
    // rtmp url
    if(!RTMP_SetupURL(rtmp, (char *)url.c_str()))
    {
        RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");
        RTMP_Free(rtmp);
        CleanupSockets();
        return -1;
    }

    if (bLiveStream) {
        rtmp->Link.lFlags |= RTMP_LF_LIVE;
    }

    // 1 hour
    RTMP_SetBufferMS(rtmp, 3600 * 1000);

    if (!RTMP_Connect(rtmp, NULL)) {
        RTMP_Log(RTMP_LOGERROR, "Connect Error");
        RTMP_Free(rtmp);
        return 0;
    }

    if (!RTMP_ConnectStream(rtmp, 0)){
        RTMP_Log(RTMP_LOGERROR, "ConnectStream Error");
        RTMP_Free(rtmp);
        return 0;
    }

    cout << "Initial RTMP connect success!" << endl;
    return 1;
}

void RtmpRecv::recv_send()
{
    /** 初始化 rtpHeader
     *  ts: RTP_PAYLOAD_TYPE_MP2T 33，RFC 指定
     * flv: RTP_PAYLOAD_TYPE_FLV  77，自定义的
     */
    rtpPacket->rtpHeaderInit(0, 0, 0, RTP_VERSION, RTP_PAYLOAD_TYPE_FLV, 0, 0, 0, 0x88923423);
    
    int nRead;
    int n = 0;
    while((nRead = RTMP_Read(rtmp, buf, bufSize)) != 0) {
        // 相当于调用 nRead 次 `int fputc(int ch, FILE* stream)`
        fwrite(buf, 1, static_cast<size_t>(nRead), fp);
        countBufSize += nRead;
        RTMP_LogPrintf("Receive: %5dByte, Total: %5.2fkB\n", nRead, countBufSize / 1024.0);

        assert (nRead <= RTP_MAX_PKT_SIZE + RTP_HEADER_SIZE);

        // RTP header 转网络序
        rtpPacket->mRtpHeader->seq = htons(rtpPacket->mRtpHeader->seq);
        rtpPacket->mRtpHeader->timestamp = htonl(rtpPacket->mRtpHeader->timestamp);
        rtpPacket->mRtpHeader->ssrc = htonl(rtpPacket->mRtpHeader->ssrc);

        // 构造 rtpPacket->mBuffer
        memcpy(rtpPacket->mBuffer, rtpPacket->mRtpHeader, sizeof(*rtpPacket->mRtpHeader));
        assert(sizeof(*rtpPacket->mRtpHeader) == RTP_HEADER_SIZE);
        memcpy(rtpPacket->payload, buf, nRead);
        memcpy(rtpPacket->mBuffer + RTP_HEADER_SIZE, rtpPacket->payload, nRead);
        rtpPacket->mSize = RTP_HEADER_SIZE + nRead;

        printf("%x %x\n", *buf, *(buf+1));
        printf("%x %x\n", *(rtpPacket->mBuffer+12), *(rtpPacket->mBuffer + 13));
        
        // 发送 rtpPacket
        // printf("RTP version: %u\n", rtpPacket->mRtpHeader->version);
        rtpInstance->send(rtpPacket);
        printf("RTP send: %d data to %s:%u\n", rtpPacket->mSize, destIP.c_str(), destPort);
        // printf("\033[1A"); // 先回到上一行
        // printf("\033[K");  // 清除该行

        // 发送只有维护 rtpHeader 序列号和时间戳
        rtpPacket->mRtpHeader->seq = ntohs(rtpPacket->mRtpHeader->seq) + 1;
        rtpPacket->mRtpHeader->timestamp = ntohl(rtpPacket->mRtpHeader->timestamp) + 90000 / FPS;
        rtpPacket->mRtpHeader->ssrc = ntohl(rtpPacket->mRtpHeader->ssrc);
        usleep(1000*1000 / FPS);
        
        // if (++ n == 5) {
        //     break;
        // }
    }
    RTMP_LogPrintf("Exit or Read finish.\n");
}